package com.haredot.controller;

import com.haredot.dto.AlipayDTO;
import com.haredot.holder.TokenContextHolder;
import com.haredot.properties.AlipayProperties;
import com.haredot.service.AlipayService;
import com.haredot.vo.R;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Base64;
import java.util.Map;

@RestController
@RequestMapping("/alipay")
@EnableConfigurationProperties(AlipayProperties.class)
public class AlipayController {

    @Resource
    private AlipayService alipayService ;

    @Resource
    private AlipayProperties alipayProperties ;

    /**
     * 添加限流逻辑
     */
    @PostMapping("/generator/order/{id}")
    public R<?> generatorOrder(@PathVariable("id")Long id, Authentication authentication)throws Exception {
        Long userId = TokenContextHolder.getCurrentUserId();
        return alipayService.generatorPayPage(id, userId);
    }

    @PutMapping("/pay/check/{orderNum}")
    public R<?> checkOrder(@PathVariable("orderNum")String orderNum) throws Exception {
        return alipayService.checkOrder(orderNum);
    }

    @PostMapping("/pay/{orderNum}")
    public R<?> generatorOrder(@PathVariable("orderNum")String orderNum) throws Exception {
        return alipayService.payOrder(orderNum);
    }

    @GetMapping("/callback")
    public R<?> callback(@RequestParam Map<String, String> params)throws Exception {
        // 对传入的参数 进行 校验
        return alipayService.checkParam(params);
    }

    /**
     *  异步通知 必须返回 success , 支付包 才认为 异步通知成功，否则 其它任何字符串，
     *  支付宝 均认为 异步通知失败 ，
     *
     *  异步通知 地址：
     *      该网址 必须是 公网地址， 否则 支付宝 无法进行异步通知 。
     */
    @PostMapping("/notify")
    public String notify(@RequestParam Map<String, String> params)throws Exception {
        // 对传入的参数 进行 校验
        R<?> r = alipayService.checkParam(params);
        return r.getStatus() ? "success" : "error" ;
    }

    /**
     * @param state : 用来标记是否记住我 ， on / off
     */
    @GetMapping("/login")
    public ModelAndView authorizeUrl(@RequestParam(value = "state", required = false, defaultValue = "on") String state) {

        String authorizeReturnUri = alipayProperties.getAuthorizeReturnUri();
        String base64State = Base64.getEncoder().encodeToString(state.getBytes(StandardCharsets.UTF_8));

        String authorizeUrl =  MessageFormat.format("{0}?app_id={1}&redirect_uri={2}&state={3}",
                alipayProperties.getAuthorizeUrl(), alipayProperties.getAppId(),
                URLEncoder.encode(authorizeReturnUri, StandardCharsets.UTF_8), base64State);

        return new ModelAndView("redirect:" + authorizeUrl);
    }

    @PostMapping("/codeToToken")
    public R<?> codeToToken(@RequestBody @Valid AlipayDTO alipayDTO)throws Exception {
        return alipayService.authCodeToToken(alipayDTO);
    }

}
